package sy4_Creational_Pattern.prototype;

/*
 * 原型模式用于复制已有对象，以提高相同类型对象的创建效率。
 * 角色1：抽象原型类Prototype，定义克隆原型对象的抽象方法。
 * 角色2：具体原型类ConcretePrototype，作为Prototype的子类，重写抽象方法。
 * 要点：Client关联Prototype。
 * 注意：通过克隆方法创建的对象是全新的对象，在内存中拥有新的地址。
 * 本例是通用实现方法。
 */
abstract class Prototype {  //角色1：抽象原型类Prototype
    protected String attribute;  //属性

    public Prototype(String attribute) { //构造器
        this.attribute = attribute;
    }

    public String getAttribute() {  //getter方法
        return attribute;
    }

    public abstract Prototype clone();  //抽象的克隆方法
}

class ConcretePrototypeA extends Prototype {  //角色2：具体原型类
    public ConcretePrototypeA(String attribute) {  //构造器
        super(attribute);  //调用父类的构造器
    }

    @Override
    public Prototype clone() {  //重写抽象的克隆方法
        //创建一个原型对象
        Prototype prototype = new ConcretePrototypeA(getAttribute());
        return prototype;  //返回一个原型对象
    }
}

class ConcretePrototypeB extends Prototype {
    public ConcretePrototypeB(String attribute) {
        super(attribute);
    }

    @Override
    public Prototype clone() {
        Prototype prototype = new ConcretePrototypeB(getAttribute());
        return prototype;
    }
}

public class Client {
    static Prototype prototype, copy;  //Client关联prototype
    static Prototype prototype2, copy2;

    public static void main(String[] args) {
        prototype = new ConcretePrototypeA("attri");
        copy = (ConcretePrototypeA) prototype.clone();
        System.out.println("原对象：" + prototype);
        System.out.println("原对象String类型的属性：" + prototype.getAttribute());
        System.out.println("克隆对象：" + copy);
        System.out.println("克隆对象String类型的属性：" + copy.getAttribute());

        System.out.println("===============================================");
        prototype2 = new ConcretePrototypeB("attri123");
        copy2 = (ConcretePrototypeB) prototype2.clone();
        System.out.println("原对象：" + prototype2);
        System.out.println("原对象String类型的属性：" + prototype2.getAttribute());
        System.out.println("克隆对象：" + copy2);
        System.out.println("克隆对象String类型的属性：" + copy2.getAttribute());
    }
}
